<!--
table的列的开关/顺序控制

参数：
tableColumns - 列定义，如：
[
  {
    label: '客商ID',
    name: 'mfId',
    field: 'mfId',
    sortable: true,
    align: 'left'
    defOrder: 1,      // 默认次序
    defVisible: true  // 默认是否显示
  },
  {
    label: '简称',
    name: 'abbrName',
    field: 'abbrName',
    sortable: true,
    align: 'left',
    defOrder: 2,
    defVisible: true
  },
  // ...
]

visibleColumns - 显示的列及次序，如：
[
  'mfId',
  'abbrName',
  // ...
]

事件：
'update:table-columns': 选项发生变化，传回的参数与tableColumns的格式完全相同
'update:visible-columns': 选项发生变化，传回的参数与visibleColumns的格式完全相同
'update-col-options-for-save': 点确定时返回这个数组，这个数组可以保存到localStorage中去，以便下次页面加载时候能够根据其内容还原列配置，其格式如下：
  [
    {name: 'mfId', visible: true},
    {name: 'abbrName', visible: false},
    //...
  ]
  还原时候尝试从localStorage中读取之，如能读取到，利用它对tableColumns进行排列(misc.sortByKeys方法没忘记吧？)，再从中提取visible为true的name到visibleColumns去
  这些动作要封装在公共方法中
-->

<template>
  <div>
    <q-btn icon="view_list" flat dense @click="onOpenOptions" :title="$t('列选项')" :ripple="false" />
    <q-dialog position="top" v-model="dlgState" transition-show="none" transition-hide="none">
      <q-card style="max-width:300px; width:300px; top: 50px" class="q-pa-sm">
        <q-card-section class="q-pa-none">
          <div class="text-h6">{{$t('列选项')}}</div>
        </q-card-section>
        <q-checkbox :label="$t('全部')" color="primary" :model-value="isAllChecked" @click="onCheckAll" dense class="q-py-xs" />
        <q-separator />
        <q-scroll-area style="height: 203px" :visible="true">
          <div v-for="opt in $d.internalOptList" :key="opt.name"
            :class="{'row':true, 'items-center':true, 'bg-grey-4':(opt.name===selectedColName) }"
            @click="selectColumn(opt)">
            <q-checkbox :label="opt.label" color="primary" v-model="$d.internalVisibleCols" :val="opt.name"
              @click="selectColumn(opt)" dense class="q-py-xs" />
          </div>
        </q-scroll-area>
        <q-separator />
        <div class="row q-gutter-xs q-pt-sm">
          <q-btn color="primary" outline size="sm" icon="fas fa-arrow-up" :title="$t('上移')" @click="moveSelectedOptionUp"
            :disable="selectedColIndex<=0" />
          <q-btn color="primary" outline size="sm" icon="fas fa-arrow-down" :title="$t('下移')" @click="moveSelectedOptionDown"
            :disable="selectedColIndex<0||selectedColIndex>=$d.internalOptList.length-1" />
          <q-btn color="primary" outline size="sm" icon="refresh" :title="$t('重置本次选择')" @click="resetOptionsOfThisTerm" />
          <q-btn color="primary" outline size="sm" icon="eva-settings-2" :title="$t('恢复默认')" @click="resetOptionsToDefault" />
          <q-space />
          <q-btn v-close-popup color="primary" :label="$t('确定')" @click="onConfirm" no-caps/>
          <q-btn v-close-popup unelevated color="primary" :label="$t('取消')" outline no-caps/>
        </div>
      </q-card>
    </q-dialog>
  </div>
</template>
<script lang="ts">
export default {
  name: 'tableColOptionsCfg'
}
</script>

<script lang="ts" setup>
import _ from 'lodash'
import {ColumnInfo, ColumnOption} from '../defs/comm';
import {computed, reactive, ref} from 'vue';

interface PropsDef {
  visibleColumns: string[],
  tableColumns: ColumnInfo[]
}

const props = withDefaults(defineProps<PropsDef>(), {
  visibleColumns: () => [],
  tableColumns: () => []
})

// 转换过的内部结构
interface InternalColInfo {
  name: string,
  label: string
}

// 本页数据
const $d = reactive({
  // 转换过的内部列表
  internalOptList: [] as InternalColInfo[],
  // 内部可见列
  internalVisibleCols: [] as string[]
})

// 对话框显示/隐藏状态
const dlgState = ref(false)

// 当前选中的列的name, 空字符串表示没选中的
const selectedColName = ref('')

// 是否所有选项都勾选中
const isAllChecked = computed(() => {
  if ($d.internalOptList.length === 0) {
    return null
  }
  if ($d.internalVisibleCols.length === $d.internalOptList.length) {
    return true
  }
  if ($d.internalVisibleCols.length === 0) {
    return false
  }
  return null
})

//选中所有
const onCheckAll = function () {
  let newCheckState = !(isAllChecked.value === true)
  if (newCheckState) {
    $d.internalVisibleCols = _.map($d.internalOptList, 'name')
  } else {
    $d.internalVisibleCols = []
  }
}

// 重置选项，如果toDefault为true，则表示恢复默认的
const resetOptionList = function (toDefault = false) {
  let tableColumnsInput = props.tableColumns
  if (toDefault) {
    tableColumnsInput = _.sortBy(props.tableColumns, function (o) {
      return o.defOrder ?? 0
    })
  }
  const internalOptList: InternalColInfo[] = []
  _.forEach(tableColumnsInput, (o) => {
    internalOptList.push({
      name: o.name,
      label: o.label
    })
  })
  $d.internalOptList = internalOptList

  if (toDefault) {
    let visibleCols: string[] = []
    _.forEach(tableColumnsInput, (o) => {
      if (o.defVisible) {
        visibleCols.push(o.name)
      }
    })
    $d.internalVisibleCols = visibleCols
  } else {
    $d.internalVisibleCols = _.clone(props.visibleColumns)
  }
}

const onOpenOptions = function () {
  resetOptionList()
  selectedColName.value = ''
  dlgState.value = true
}

const selectColumn = function (opt: InternalColInfo) {
  selectedColName.value = opt.name
}

const selectedColIndex = computed(() => {
  if (!selectedColName.value) {
    return -1
  }
  return _.findIndex($d.internalOptList, ['name', selectedColName.value])
})

const moveSelectedOptionUp = function () {
  if (selectedColIndex.value <= 0) {
    return
  }
  let idx = selectedColIndex.value
  let colsToSwap = [$d.internalOptList[idx - 1], $d.internalOptList[idx]]
  $d.internalOptList.splice(idx - 1, 2, colsToSwap[1], colsToSwap[0])
}

const moveSelectedOptionDown = function () {
  if (selectedColIndex.value < 0 || selectedColIndex.value >= $d.internalOptList.length - 1) {
    return
  }
  let idx = selectedColIndex.value
  let colsToSwap = [$d.internalOptList[idx], $d.internalOptList[idx + 1]]
  $d.internalOptList.splice(idx, 2, colsToSwap[1], colsToSwap[0])
}

const resetOptionsOfThisTerm = function () {
  resetOptionList()
  selectedColName.value = ''
}

const resetOptionsToDefault = function () {
  resetOptionList(true)
  selectedColName.value = ''
}

const emit = defineEmits<{
  (e:'update:table-columns', data:ColumnInfo[]):void
  (e:'update:visible-columns', data: string[]):void
  (e:'update-col-options-for-save', data:ColumnOption[]):void
}>()

const onConfirm = function () {
  const v = $f.misc.sortByKeys(props.tableColumns, 'name', _.map($d.internalOptList, 'name'))
  emit('update:table-columns', v as ColumnInfo[] )
  emit('update:visible-columns', $d.internalVisibleCols)
  let optionToSave:ColumnOption[] = []
  _.forEach($d.internalOptList, (o) => {
    optionToSave.push({
      name: o.name,
      visible: _.indexOf($d.internalVisibleCols, o.name) >= 0
    })
  })
  emit('update-col-options-for-save', optionToSave)
}

</script>
